package repository;

import java.io.File;
import java.io.FilenameFilter;
import java.io.FileFilter;
import java.io.IOException;

import java.util.Vector;
import repository.exception.CreateDirException;
import repository.exception.DataFileException;
import repository.exception.FileExistException;
import repository.exception.FileSizeException;
import repository.exception.NoRepositoryException;
import repository.exception.NonDirPathException;
import repository.exception.NullRootException;
import repository.exception.RepositoryException;
import repository.exception.RepositorySizeException;

/**
 * Интерфейс репозитория.
 * Содержет функции работы с репоториями пользователей.
 * Позволяет проводить настройку и работать с файлами пользователей.
 * Все репозитории располагаются в общей корневой директории.
 * Корневая директория настраивается пользователем класса или
 * создается по-умолчанию. Каждому репозиторию соответствует отдельная диретория.
 * Класс сам определяет имена директорий репозиториев пользователей.
 * Для работы с репозиторием необходимо знать идентификатор пользователя
 * @author Aleksey & rd
 * @version alpha
 */
public interface IRepository {

    /**
     * Задать корневую директорию всех репозиториев
     * @param path корневая директория. При передаче в качестве параметра
     * null-значение, генерирует NullPointerException
     */
    public void setRootPath (File path);

    /**
     * Запросить корневую директорию всех репозиториев
     * @return корневая директория
     */
    public File getRootPath ();

    /**
     * Установить корневую директорию по-умолчанию: "./repositories".
     * Метод НЕ создает директорию в случае её отсутствия.
     * Для проверки структуры репозитория вызвать метод checkWholeness().
     */
    public void initRootPath ();

    /**
     * Проверить целостность репозитория. Проверяется наличие корневой диретории
     * и директорий пользователей. Отсутствующие диретории будут созданы.
     * @throws repository.exception.NullRootException - не задан корень
     * @throws java.io.IOException - ошибка при создании директорий
     */
    public void checkWholeness() throws NullRootException,IOException;

    /**
     * создать репозиторий пользователя
     * @param userID идентификатор пользователя
     * @return true в случае успеха, false если репозиторий существует или
     * userID<0
     * @throws repository.exception.NullRootException не установлена корневая
     * директория
     * @throws repository.exception.CreateDirException ошибка при создании
     * директории репозитория
     */
    public boolean createRepository (long userID)
            throws NullRootException,CreateDirException;

    /**
     * создать репозиторий пользователя
     * @param userID идентификатор пользователя
     * @param params параметры репозитория. В случае null будут заданы умолчания
     * @return true в случае успеха, false если репозиторий существует или
     * userID<0
     * @throws repository.exception.NullRootException не установлена корневая
     * директория
     * @throws repository.exception.CreateDirException ошибка при создании
     * директории репозитория
     */
    public boolean createRepository (long userID, RepositoryParams params)
            throws NullRootException,CreateDirException;

    /**
     * Запросить репозиторий пользователя
     * @param userID идентификатор пользователя
     * @return директория репозитория или null, если репозитория нет
     * @throws repository.exception.RepositoryException ошибка при чтении репозитория
     */
    public File getRepository (long userID) throws RepositoryException;

    /**
     * Проверить существование репозитория пользователя
     * @param userID идентификатор пользователя
     * @return утверждение/отрицание существования репозитория
     * @throws repository.exception.RepositoryException ошибка при чтении репозитория
     */
    public boolean isRepositoryExist (long userID) throws RepositoryException;

    /**
     * Удалить репозиторий пользователя
     * @param userID иденитификатор пользователя
     * @return true - успешное удаление, иначе false
     * @throws repository.exception.NullRootException не задана корневая директория
     * @throws repository.exception.NoRepositoryException отсутствует репозиторий
     */
    public boolean deleteRepository (long userID) 
            throws NullRootException,NoRepositoryException;

    /**
     * Запросить все репозитории в корневой директории
     * @return массив репозиториев
     * @throws repository.exception.NullRootException не задана корневая директория
     */
    public File[] getRepositories () throws NullRootException;

    /**
     * Запросить файл по относительному пути
     * @param userID иденитификатор пользователя
     * @param relativePath путь относительно репозитория пользователя
     * @return файл или директория
     * @throws repository.exception.NullRootException корневая директория не задана
     * @throws repository.exception.NoRepositoryException отсутствует репозиторий
     */
    public File getFile(long userID,String relativePath)
            throws NullRootException,NoRepositoryException;

    /**
     * Запросить путь до файла по относительному пути
     * @param userID иденитификатор пользователя
     * @param relativePath путь относительно репозитория пользователя
     * @return путь до файла
     * @throws repository.exception.NullRootException корневая директория не задана
     * @throws repository.exception.NoRepositoryException отсутствует репозиторий
     */
    public String getFilePath(long userID,String relativePath)
            throws NullRootException,NoRepositoryException;

    /**
     * Запросить файлы и директории репозитория лежащие в директории relativePath
     * @param userID иденитификатор пользователя
     * @param relativePath путь директории относительно репозитория пользователя
     * @return массив файлов, null в случае если директории не существует
     * @throws repository.exception.NullRootException корневая директория не задана
     * @throws repository.exception.NoRepositoryException отсутствует репозиторий
     */
    public String[] getFiles (long userID,String relativePath)
            throws NullRootException,NoRepositoryException;

    /**
     * Запросить файлы и директории репозитория лежащие в директории relativePath
     * @param userID иденитификатор пользователя
     * @param relativePath путь директории относительно репозитория пользователя
     * @param filter фильтр файлов по имени
     * @return массив файлов, null в случае если директории не существует
     * @throws repository.exception.NullRootException корневая директория не задана
     * @throws repository.exception.NoRepositoryException отсутствует репозиторий
     */
    public String[] getFiles(long userID,String relativePath,
            FilenameFilter filter) throws NullRootException,NoRepositoryException;

    /**
     * Запросить файлы и директории репозитория лежащие в директории relativePath
     * @param userID иденитификатор пользователя
     * @param relativePath путь директории относительно репозитория пользователя
     * @param filter фильтр файлов
     * @return массив файлов, null в случае если директории не существует
     * @throws repository.exception.NullRootException корневая директория не задана
     * @throws repository.exception.NoRepositoryException отсутствует репозиторий
     */
    /*public String[] getFiles(long userID,String relativePath,
            FileFilter filter) throws NullRootException,NoRepositoryException;*/

    /**
     * Запросить файл или директорию
     * @param userID иденитификатор пользователя
     * @param relativePath путь относительно репозитория пользователя
     * @return файл или директория
     * @throws repository.exception.NullRootException корневая директория не задана
     * @throws repository.exception.NoRepositoryException отсутствует репозиторий
     */
    /*public String getFile(long userID,String relativePath)
            throws NullRootException,NoRepositoryException ;*/

    /**
     * Скачать файл с репозитория
     * @param userID иденитификатор пользователя
     * @param relativePath путь относительно репозитория пользователя
     * @return массив байт, если файла не существует или
     * relativePath - директория возвращает null;
     * @throws repository.exception.NullRootException корневая директория не задана
     * @throws repository.exception.NoRepositoryException отсутствует репозиторий
     * @throws java.io.IOException ошибка чтения файла
     */
    public ByteArray downloadFile (long userID,String relativePath)
            throws IOException,NullRootException,NoRepositoryException ;

    /**
     * Загрузить файл в репозиторий
     * @param userID  иденитификатор пользователя
     * @param relativePath путь относительно репозитория пользователя
     * @param array массив байт
     * @return true в случае успеха, иначе false
     * @throws java.io.IOException ошибка чтения файла
     * @throws repository.exception.NullRootException корневая директория не задана
     * @throws repository.exception.NoRepositoryException отсутствует репозиторий
     * @throws repository.exception.FileSizeException превышен размер файла
     * @throws repository.exception.RepositorySizeException превышен размер репозитория
     */
    public boolean uploadFile(long userID,String relativePath, ByteArray array)
            throws IOException,NullRootException,NoRepositoryException,
            FileSizeException,RepositorySizeException ;

    /**
     * Проверить явяется ли файл с заданным именем директорией
     * @param userID иденитификатор пользователя
     * @param relativePath путь относительно репозитория пользователя
     * @return true если директория
     * @throws repository.exception.NullRootException корневая директория не задана
     * @throws repository.exception.NoRepositoryException отсутствует репозиторий
     */
    public boolean isDirectory(long userID,String relativePath)
            throws NullRootException,NoRepositoryException ;


    /**
     * Добавить файл в репозиторий
     * @param userID иденитификатор пользователя
     * @param file добавляемый файл
     * @param relativePath путь относительно репозитория пользователя
     * @return ture - в случае успеха, false - файл существует
     * @throws NullRootException  корневая директория не задана
     * @throws IOException ошибка ввода/вывода при копировании файла
     * @throws NoRepositoryException отсутствует репозиторий
     * @throws FileSizeException превышен размер файла
     * @throws RepositorySizeException превышен размер репозитория
     */
    /*public boolean createFile (long userID, File file, String relativePath)
            throws NullRootException, IOException,
            NoRepositoryException,FileSizeException,RepositorySizeException;*/

    /**
     * Создать папку в директории репозитория
     * @param userID иденитификатор пользователя
     * @param relativePath путь относительно репозитория пользователя
     * @return ture - в случае успеха, иначе false
     * @throws repository.exception.NullRootException корневая директория не задана
     * @throws repository.exception.NoRepositoryException отсутствует репозиторий
     * @throws repository.exception.NonDirPathException путь не является директорией
     */
    public boolean createDirectory (long userID, String relativePath)
            throws NullRootException, IOException, NoRepositoryException;

    /**
     * Удалить файл или директорию из репозитория.
     * Для удаления директории она должна быть пуста.
     * @param userID иденитификатор пользователя
     * @param relativePath путь к файлу относительно репозитория
     * @return true - успешное удаление, false в противном случае
     * @throws NullRootException корневая директория не задана
     * @throws repository.exception.NoRepositoryException нет репозитория
     */
    public boolean deleteFile (long userID, String relativePath)
            throws NullRootException, NoRepositoryException;

    /**
     * Удалить файл или директорию из репозитория.
     * В случае удаления директории удяляется и её содержимое.
     * @param userID иденитификатор пользователя
     * @param relativePath путь к файлу относительно репозитория
     * @return true - успешное удаление, false в противном случае
     * @throws NullRootException корневая директория не задана
     * @throws repository.exception.NoRepositoryException нет репозитория 
     */
    public boolean recurrenceDelete (long userID, String relativePath)
            throws NullRootException, NoRepositoryException;

    /**
     * Обновить файл репозитория
     * @param userID иденитификатор пользователя
     * @param file файл-источник
     * @param relativePath путь назначения относительно репозитория пользователя
     * @throws NullRootException корневая директория не задана
     * @throws IOException ошибка ввода/вывода при копировании файла
     * @throws NoRepositoryException нет репозитория указанного пользователя
     * @throws FileSizeException превышен размер файла
     * @throws RepositorySizeException превышен размер репозитория
     */
    /*public void updateFile (long userID, File file, String relativePath)
            throws NullRootException, IOException,
            NoRepositoryException,FileSizeException,RepositorySizeException;*/

    /**
     * Переименовать файл. Можно использовать для перемещения файла
     * @param userID иденитификатор пользователя
     * @param relativePath путь относительно репозитория пользователя
     * @param newRelativePath новый путь относительно репозитория пользователя
     * @return true в случае успеха, иначе false
     * @throws NullRootException корневая директория не задана
     * @throws NoRepositoryException нет репозитория указанного пользователя
     */
    public boolean renameFile(long userID, String relativePath,
            String newRelativePath) throws NullRootException, NoRepositoryException;

    /**
     * Провенрить существование файла или директории
     * @param userID иденитификатор пользователя
     * @param relativePath путь относительно репозитория пользователя
     * @return true в случае успеха, иначе false
     * @throws NullRootException корневая директория не задана
     * @throws NoRepositoryException нет репозитория указанного пользователя
     */
    public boolean exist(long userID, String relativePath)
            throws NullRootException, NoRepositoryException;

    /**
     * Запросить время создания файла
     * @param userID иденитификатор пользователя
     * @param relativePath путь относительно репозитория пользователя
     * @return время в милисекунах с 1970 года
     * @throws NullRootException корневая директория не задана
     * @throws NoRepositoryException нет репозитория указанного пользователя
     */
    public long lastModified(long userID, String relativePath)
            throws NullRootException, NoRepositoryException;

    /**
     * Запросить количество файлов в папке и подпапках
     * @param userID иденитификатор пользователя
     * @param relativePath путь относительно репозитория пользователя
     * @return число файлов в папке и подпапках. -1 если на relativePath не
     * существует или является файлом
     * @throws NullRootException корневая директория не задана
     * @throws NoRepositoryException нет репозитория указанного пользователя
     */
    public int getFilesNumber(long userID, String relativePath)
            throws NullRootException, NoRepositoryException;

    /**
     * запросить размер файла или директории
     * @param userID иденитификатор пользователя
     * @param relativePath путь относительно репозитория пользователя
     * @return размер файла или директории в байтах
     * @throws NullRootException корневая директория не задана
     * @throws NoRepositoryException нет репозитория указанного пользователя
     */
    public long getSize(long userID, String relativePath)
            throws NullRootException, NoRepositoryException;

    /**
     * Запросить размер корневой директории
     * @return размер директории в байтах
     * @throws repository.exception.NullRootException корневая директория не задана
     */
    public long getRootSize ()throws NullRootException ;

    /**
     * Запросить размер репозитория
     * @param userID идентификатор поьзователя
     * @return размер репозитория в байтах
     * @throws repository.exception.NullRootException корневая директория не задана
     * @throws NoRepositoryException нет репозитория указанного пользователя
     */
    public long getRepositorySize (long userID)
            throws NullRootException, NoRepositoryException;

    /**
     * Запросить параметры репозитория
     * @param userID идентификатор пользователя
     * @return параметры репозитория
     * @throws repository.exception.RepositoryException ошибка при чтении
     * значений
     */
    public RepositoryParams getRepositoryParams (long userID)
            throws RepositoryException;

    /**
     * Установить параметры репозитория
     * @param userID идентификатор пользователя
     * @param params параметры репозитория
     * @throws repository.exception.RepositoryException ошибка при
     * установке значений
     */
    public void setRepositoryParams (long userID, RepositoryParams params)
            throws RepositoryException;

    /**
     * Прочитать параметры из файла "repository.data" в директорию приложения
     * @throws repository.exception.DataFileException ошибка при чтении файла
     */
    public void loadRepositoryData () throws DataFileException;

    /**
     * Сохраняет параметры в файл "repository.data" в директорию приложения
     * формат файла: [число_записей][UserID|MaxSize|MaxFileSize]...
     * @throws repository.exception.DataFileException ошибка при записи в файл
     */
    public void saveRepositoryData () throws DataFileException;
}

